home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
ddj0492.zip
/
DFLAT.492
< prev
next >
Wrap
Text File
|
1992-03-18
|
29KB
|
960 lines
_C PROGRAMMING COLUMN_
by Al Stevens
[LISTING ONE]
/* ---------------- menubar.c ------------------ */
#include "dflat.h"
static void reset_menubar(WINDOW);
static struct {
int x1, x2; /* position in menu bar */
char sc; /* shortcut key value */
} menu[10];
static int mctr;
MBAR *ActiveMenuBar;
static MENU *ActiveMenu;
static WINDOW mwnd;
static BOOL Selecting;
static WINDOW Cascaders[MAXCASCADES];
static int casc;
static WINDOW GetDocFocus(WINDOW);
/* ----------- SETFOCUS Message ----------- */
static void SetFocusMsg(WINDOW wnd, PARAM p1)
{
if ((int)p1 && ActiveMenuBar->ActiveSelection == -1)
ActiveMenuBar->ActiveSelection = 0;
SendMessage(wnd, PAINT, 0, 0);
if (!(int)p1)
SendMessage(GetParent(wnd), ADDSTATUS, 0, 0);
}
/* --------- BUILDMENU Message --------- */
static void BuildMenuMsg(WINDOW wnd, PARAM p1)
{
int offset = 3;
reset_menubar(wnd);
mctr = 0;
ActiveMenuBar = (MBAR *) p1;
ActiveMenu = ActiveMenuBar->PullDown;
while (ActiveMenu->Title != NULL &&
ActiveMenu->Title != (void*)-1) {
char *cp;
if (strlen(GetText(wnd)+offset) <
strlen(ActiveMenu->Title)+3)
break;
GetText(wnd) = realloc(GetText(wnd),
strlen(GetText(wnd))+5);
memmove(GetText(wnd) + offset+4, GetText(wnd) + offset,
strlen(GetText(wnd))-offset+1);
CopyCommand(GetText(wnd)+offset,ActiveMenu->Title,FALSE,
wnd->WindowColors [STD_COLOR] [BG]);
menu[mctr].x1 = offset;
offset += strlen(ActiveMenu->Title) + (3+MSPACE);
menu[mctr].x2 = offset-MSPACE;
cp = strchr(ActiveMenu->Title, SHORTCUTCHAR);
if (cp)
menu[mctr].sc = tolower(*(cp+1));
mctr++;
ActiveMenu++;
}
ActiveMenu = ActiveMenuBar->PullDown;
}
/* ---------- PAINT Message ---------- */
static void PaintMsg(WINDOW wnd)
{
if (wnd == inFocus)
SendMessage(GetParent(wnd), ADDSTATUS, 0, 0);
SetStandardColor(wnd);
wputs(wnd, GetText(wnd), 0, 0);
if (ActiveMenuBar->ActiveSelection != -1 &&
(wnd == inFocus || mwnd != NULL)) {
char *sel;
char *cp;
if ((sel = malloc(200)) != NULL) {
int offset=menu[ActiveMenuBar->ActiveSelection].x1;
int offset1=menu[ActiveMenuBar->ActiveSelection].x2;
GetText(wnd)[offset1] = '\0';
SetReverseColor(wnd);
memset(sel, '\0', 200);
strcpy(sel, GetText(wnd)+offset);
cp = strchr(sel, CHANGECOLOR);
if (cp != NULL)
*(cp + 2) = background | 0x80;
wputs(wnd, sel,
offset-ActiveMenuBar->ActiveSelection*4, 0);
GetText(wnd)[offset1] = ' ';
if (!Selecting && mwnd == NULL && wnd == inFocus) {
char *st = ActiveMenu
[ActiveMenuBar->ActiveSelection].StatusText;
if (st != NULL)
SendMessage(GetParent(wnd), ADDSTATUS,
(PARAM)st, 0);
}
free(sel);
}
}
}
/* ------------ KEYBOARD Message ------------- */
static void KeyboardMsg(WINDOW wnd, PARAM p1)
{
MENU *mnu;
if (mwnd == NULL) {
/* ----- search for menu bar shortcut keys ---- */
int c = tolower((int)p1);
int a = AltConvert((int)p1);
int j;
for (j = 0; j < mctr; j++) {
if ((inFocus == wnd && menu[j].sc == c) ||
(a && menu[j].sc == a)) {
SendMessage(wnd, MB_SELECTION, j, 0);
return;
}
}
}
/* -------- search for accelerator keys -------- */
mnu = ActiveMenu;
while (mnu->Title != (void *)-1) {
struct PopDown *pd = mnu->Selections;
if (mnu->PrepMenu)
(*(mnu->PrepMenu))(GetDocFocus(wnd), mnu);
while (pd->SelectionTitle != NULL) {
if (pd->Accelerator == (int) p1) {
if (pd->Attrib & INACTIVE)
beep();
else {
if (pd->Attrib & TOGGLE)
pd->Attrib ^= CHECKED;
SendMessage(GetDocFocus(wnd),
SETFOCUS, TRUE, 0);
PostMessage(GetParent(wnd),
COMMAND, pd->ActionId, 0);
}
return;
}
pd++;
}
mnu++;
}
switch ((int)p1) {
case F1:
if (ActiveMenu != NULL &&
(mwnd == NULL ||
(ActiveMenu+ActiveMenuBar->ActiveSelection)->
Selections[0].SelectionTitle == NULL)) {
DisplayHelp(wnd,
(ActiveMenu+ActiveMenuBar->ActiveSelection)->Title+1);
return;
}
break;
case '\r':
if (mwnd == NULL &&
ActiveMenuBar->ActiveSelection != -1)
SendMessage(wnd, MB_SELECTION,
ActiveMenuBar->ActiveSelection, 0);
break;
case F10:
if (wnd != inFocus && mwnd == NULL) {
SendMessage(wnd, SETFOCUS, TRUE, 0);
break;
}
/* ------- fall through ------- */
case ESC:
if (inFocus == wnd && mwnd == NULL) {
ActiveMenuBar->ActiveSelection = -1;
SendMessage(GetDocFocus(wnd),SETFOCUS,TRUE,0);
SendMessage(wnd, PAINT, 0, 0);
}
break;
case FWD:
ActiveMenuBar->ActiveSelection++;
if (ActiveMenuBar->ActiveSelection == mctr)
ActiveMenuBar->ActiveSelection = 0;
if (mwnd != NULL)
SendMessage(wnd, MB_SELECTION,
ActiveMenuBar->ActiveSelection, 0);
else
SendMessage(wnd, PAINT, 0, 0);
break;
case BS:
if (ActiveMenuBar->ActiveSelection == 0)
ActiveMenuBar->ActiveSelection = mctr;
--ActiveMenuBar->ActiveSelection;
if (mwnd != NULL)
SendMessage(wnd, MB_SELECTION,
ActiveMenuBar->ActiveSelection, 0);
else
SendMessage(wnd, PAINT, 0, 0);
break;
default:
break;
}
}
/* --------------- LEFT_BUTTON Message ---------- */
static void LeftButtonMsg(WINDOW wnd, PARAM p1)
{
int i;
int mx = (int) p1 - GetLeft(wnd);
/* --- compute the selection that the left button hit --- */
for (i = 0; i < mctr; i++)
if (mx >= menu[i].x1-4*i &&
mx <= menu[i].x2-4*i-5)
break;
if (i < mctr)
if (i != ActiveMenuBar->ActiveSelection || mwnd == NULL)
SendMessage(wnd, MB_SELECTION, i, 0);
}
/* -------------- MB_SELECTION Message -------------- */
static void SelectionMsg(WINDOW wnd, PARAM p1, PARAM p2)
{
int wd, mx, my;
MENU *mnu;
Selecting = TRUE;
mnu = ActiveMenu+(int)p1;
if (mnu->PrepMenu != NULL)
(*(mnu->PrepMenu))(GetDocFocus(wnd), mnu);
wd = MenuWidth(mnu->Selections);
if (p2) {
mx = GetLeft(inFocus) + WindowWidth(inFocus) - 1;
my = GetTop(inFocus) + inFocus->selection;
}
else {
int offset = menu[(int)p1].x1 - 4 * (int)p1;
if (mwnd != NULL) {
SendMessage(wnd, SETFOCUS, TRUE, 0);
SendMessage(mwnd, CLOSE_WINDOW, 0, 0);
}
ActiveMenuBar->ActiveSelection = (int) p1;
if (offset > WindowWidth(wnd)-wd)
offset = WindowWidth(wnd)-wd;
mx = GetLeft(wnd)+offset;
my = GetTop(wnd)+1;
}
mwnd = CreateWindow(POPDOWNMENU, NULL,
mx, my,
MenuHeight(mnu->Selections),
wd,
NULL,
wnd,
NULL,
0);
AddAttribute(mwnd, SHADOW);
if (mnu->Selections[0].SelectionTitle != NULL) {
SendMessage(mwnd, BUILD_SELECTIONS, (PARAM) mnu, 0);
SendMessage(mwnd, SETFOCUS, TRUE, 0);
}
else
SendMessage(wnd, PAINT, 0, 0);
Selecting = FALSE;
}
/* --------- COMMAND Message ---------- */
static void CommandMsg(WINDOW wnd, PARAM p1, PARAM p2)
{
if (isCascadedCommand(ActiveMenuBar, (int)p1)) {
/* find the cascaded menu based on command id in p1 */
MENU *mnu = ActiveMenu+mctr;
while (mnu->Title != (void *)-1) {
if (mnu->CascadeId == (int) p1) {
if (casc < MAXCASCADES) {
Cascaders[casc++] = mwnd;
SendMessage(wnd, MB_SELECTION,
(PARAM)(mnu-ActiveMenu), TRUE);
}
break;
}
mnu++;
}
}
else {
if (mwnd != NULL)
SendMessage(mwnd, CLOSE_WINDOW, 0, 0);
SendMessage(GetDocFocus(wnd), SETFOCUS, TRUE, 0);
PostMessage(GetParent(wnd), COMMAND, p1, p2);
}
}
/* --------------- CLOSE_POPDOWN Message --------------- */
static void ClosePopdownMsg(WINDOW wnd)
{
if (casc > 0)
SendMessage(Cascaders[--casc], CLOSE_WINDOW, 0, 0);
else {
mwnd = NULL;
ActiveMenuBar->ActiveSelection = -1;
if (!Selecting)
SendMessage(GetDocFocus(wnd), SETFOCUS, TRUE, 0);
SendMessage(wnd, PAINT, 0, 0);
}
}
/* ---------------- CLOSE_WINDOW Message --------------- */
static void CloseWindowMsg(WINDOW wnd)
{
if (GetText(wnd) != NULL) {
free(GetText(wnd));
GetText(wnd) = NULL;
}
mctr = 0;
ActiveMenuBar->ActiveSelection = -1;
ActiveMenu = NULL;
ActiveMenuBar = NULL;
}
/* --- Window processing module for MENUBAR window class --- */
int MenuBarProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
{
int rtn;
switch (msg) {
case CREATE_WINDOW:
reset_menubar(wnd);
break;
case SETFOCUS:
rtn = BaseWndProc(MENUBAR, wnd, msg, p1, p2);
SetFocusMsg(wnd, p1);
return rtn;
case BUILDMENU:
BuildMenuMsg(wnd, p1);
break;
case PAINT:
if (!isVisible(wnd) || GetText(wnd) == NULL)
break;
PaintMsg(wnd);
return FALSE;
case BORDER:
return TRUE;
case KEYBOARD:
KeyboardMsg(wnd, p1);
return TRUE;
case LEFT_BUTTON:
LeftButtonMsg(wnd, p1);
return TRUE;
case MB_SELECTION:
SelectionMsg(wnd, p1, p2);
break;
case COMMAND:
CommandMsg(wnd, p1, p2);
return TRUE;
case INSIDE_WINDOW:
return InsideRect(p1, p2, WindowRect(wnd));
case CLOSE_POPDOWN:
ClosePopdownMsg(wnd);
return TRUE;
case CLOSE_WINDOW:
rtn = BaseWndProc(MENUBAR, wnd, msg, p1, p2);
CloseWindowMsg(wnd);
return rtn;
default:
break;
}
return BaseWndProc(MENUBAR, wnd, msg, p1, p2);
}
/* ----- return the WINDOW handle of the document window
that had the focus when the MENUBAR was activated ----- */
static WINDOW GetDocFocus(WINDOW wnd)
{
WINDOW DocFocus = Focus.LastWindow;
CLASS cl;
while ((cl = GetClass(DocFocus)) == MENUBAR ||
cl == POPDOWNMENU ||
cl == STATUSBAR ||
cl == APPLICATION) {
if ((DocFocus = PrevWindow(DocFocus)) == NULL) {
DocFocus = GetParent(wnd);
break;
}
}
return DocFocus;
}
/* ------------- reset the MENUBAR -------------- */
static void reset_menubar(WINDOW wnd)
{
if ((GetText(wnd) =
realloc(GetText(wnd), SCREENWIDTH+5)) != NULL) {
memset(GetText(wnd), ' ', SCREENWIDTH);
*(GetText(wnd)+WindowWidth(wnd)) = '\0';
}
}
[LISTING TWO]
/* ------------- popdown.c ----------- */
#include "dflat.h"
static int SelectionWidth(struct PopDown *);
static int py = -1;
/* ------------ CREATE_WINDOW Message ------------- */
static int CreateWindowMsg(WINDOW wnd)
{
int rtn;
ClearAttribute(wnd, HASTITLEBAR |
VSCROLLBAR |
MOVEABLE |
SIZEABLE |
HSCROLLBAR);
rtn = BaseWndProc(POPDOWNMENU, wnd, CREATE_WINDOW, 0, 0);
SendMessage(wnd, CAPTURE_MOUSE, 0, 0);
SendMessage(wnd, CAPTURE_KEYBOARD, 0, 0);
SendMessage(NULL, SAVE_CURSOR, 0, 0);
SendMessage(NULL, HIDE_CURSOR, 0, 0);
return rtn;
}
/* --------- LEFT_BUTTON Message --------- */
static void LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
{
int my = (int) p2 - GetTop(wnd);
if (InsideRect(p1, p2, ClientRect(wnd))) {
if (my != py) {
SendMessage(wnd, LB_SELECTION,
(PARAM) wnd->wtop+my-1, TRUE);
py = my;
}
}
else if ((int)p2 == GetTop(GetParent(wnd)))
if (GetClass(GetParent(wnd)) == MENUBAR)
PostMessage(GetParent(wnd), LEFT_BUTTON, p1, p2);
}
/* -------- BUTTON_RELEASED Message -------- */
static BOOL ButtonReleasedMsg(WINDOW wnd, PARAM p1, PARAM p2)
{
py = -1;
if (InsideRect((int)p1, (int)p2, ClientRect(wnd))) {
int sel = (int)p2 - GetClientTop(wnd);
if (*TextLine(wnd, sel) != LINE)
SendMessage(wnd, LB_CHOOSE, wnd->selection, 0);
}
else {
WINDOW pwnd = GetParent(wnd);
if (GetClass(pwnd) == MENUBAR && (int)p2==GetTop(pwnd))
return FALSE;
if ((int)p1 == GetLeft(pwnd)+2)
return FALSE;
SendMessage(wnd, CLOSE_WINDOW, 0, 0);
return TRUE;
}
return FALSE;
}
/* --------- PAINT Message -------- */
static void PaintMsg(WINDOW wnd)
{
int wd;
unsigned char sep[80], *cp = sep;
unsigned char sel[80];
struct PopDown *ActivePopDown;
struct PopDown *pd1;
ActivePopDown = pd1 = wnd->mnu->Selections;
wd = MenuWidth(ActivePopDown)-2;
while (wd--)
*cp++ = LINE;
*cp = '\0';
SendMessage(wnd, CLEARTEXT, 0, 0);
wnd->selection = wnd->mnu->Selection;
while (pd1->SelectionTitle != NULL) {
if (*pd1->SelectionTitle == LINE)
SendMessage(wnd, ADDTEXT, (PARAM) sep, 0);
else {
int len;
memset(sel, '\0', sizeof sel);
if (pd1->Attrib & INACTIVE)
/* ------ inactive menu selection ----- */
sprintf(sel, "%c%c%c",
CHANGECOLOR,
wnd->WindowColors [HILITE_COLOR] [FG]|0x80,
wnd->WindowColors [STD_COLOR] [BG]|0x80);
strcat(sel, " ");
if (pd1->Attrib & CHECKED)
/* ---- paint the toggle checkmark ---- */
sel[strlen(sel)-1] = CHECKMARK;
len=CopyCommand(sel+strlen(sel),pd1->SelectionTitle,
pd1->Attrib & INACTIVE,
wnd->WindowColors [STD_COLOR] [BG]);
if (pd1->Accelerator) {
/* ---- paint accelerator key ---- */
int i;
int wd1 = 2+SelectionWidth(ActivePopDown) -
strlen(pd1->SelectionTitle);
for (i = 0; keys[i].keylabel; i++) {
if (keys[i].keycode == pd1->Accelerator) {
while (wd1--)
strcat(sel, " ");
sprintf(sel+strlen(sel), "[%s]",
keys[i].keylabel);
break;
}
}
}
if (pd1->Attrib & CASCADED) {
/* ---- paint cascaded menu token ---- */
if (!pd1->Accelerator) {
wd = MenuWidth(ActivePopDown)-len+1;
while (wd--)
strcat(sel, " ");
}
sel[strlen(sel)-1] = CASCADEPOINTER;
}
else
strcat(sel, " ");
strcat(sel, " ");
sel[strlen(sel)-1] = RESETCOLOR;
SendMessage(wnd, ADDTEXT, (PARAM) sel, 0);
}
pd1++;
}
}
/* ---------- BORDER Message ----------- */
static int BorderMsg(WINDOW wnd)
{
int i, rtn = TRUE;
WINDOW currFocus;
if (wnd->mnu != NULL) {
currFocus = inFocus;
inFocus = NULL;
rtn = BaseWndProc(POPDOWNMENU, wnd, BORDER, 0, 0);
inFocus = currFocus;
for (i = 0; i < ClientHeight(wnd); i++) {
if (*TextLine(wnd, i) == LINE) {
wputch(wnd, LEDGE, 0, i+1);
wputch(wnd, REDGE, WindowWidth(wnd)-1, i+1);
}
}
}
return rtn;
}
/* -------------- LB_CHOOSE Message -------------- */
static void LBChooseMsg(WINDOW wnd, PARAM p1)
{
struct PopDown *ActivePopDown = wnd->mnu->Selections;
if (ActivePopDown != NULL) {
int *attr = &(ActivePopDown+(int)p1)->Attrib;
wnd->mnu->Selection = (int)p1;
if (!(*attr & INACTIVE)) {
if (*attr & TOGGLE)
*attr ^= CHECKED;
PostMessage(GetParent(wnd), COMMAND,
(ActivePopDown+(int)p1)->ActionId, p1);
}
else
beep();
}
}
/* ---------- KEYBOARD Message --------- */
static BOOL KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
{
struct PopDown *ActivePopDown = wnd->mnu->Selections;
if (wnd->mnu != NULL) {
if (ActivePopDown != NULL) {
int c = (int)p1;
int sel = 0;
int a;
struct PopDown *pd = ActivePopDown;
if ((c & OFFSET) == 0)
c = tolower(c);
a = AltConvert(c);
while (pd->SelectionTitle != NULL) {
char *cp = strchr(pd->SelectionTitle,
SHORTCUTCHAR);
int sc = tolower(*(cp+1));
if ((cp && sc == c) ||
(a && sc == a) ||
pd->Accelerator == c) {
PostMessage(wnd, LB_SELECTION, sel, 0);
PostMessage(wnd, LB_CHOOSE, sel, TRUE);
return TRUE;
}
pd++, sel++;
}
}
}
switch ((int)p1) {
case F1:
if (ActivePopDown == NULL)
SendMessage(GetParent(wnd), KEYBOARD, p1, p2);
else
DisplayHelp(wnd,
(ActivePopDown+wnd->selection)->help);
return TRUE;
case ESC:
SendMessage(wnd, CLOSE_WINDOW, 0, 0);
return TRUE;
case FWD:
case BS:
if (GetClass(GetParent(wnd)) == MENUBAR)
PostMessage(GetParent(wnd), KEYBOARD, p1, p2);
return TRUE;
case UP:
if (wnd->selection == 0) {
if (wnd->wlines == ClientHeight(wnd)) {
PostMessage(wnd, LB_SELECTION,
wnd->wlines-1, FALSE);
return TRUE;
}
}
break;
case DN:
if (wnd->selection == wnd->wlines-1) {
if (wnd->wlines == ClientHeight(wnd)) {
PostMessage(wnd, LB_SELECTION, 0, FALSE);
return TRUE;
}
}
break;
case HOME:
case END:
case '\r':
break;
default:
return TRUE;
}
return FALSE;
}
/* ----------- CLOSE_WINDOW Message ---------- */
static int CloseWindowMsg(WINDOW wnd)
{
int rtn;
SendMessage(wnd, RELEASE_MOUSE, 0, 0);
SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
SendMessage(NULL, RESTORE_CURSOR, 0, 0);
rtn = BaseWndProc(POPDOWNMENU, wnd, CLOSE_WINDOW, 0, 0);
SendMessage(GetParent(wnd), CLOSE_POPDOWN, 0, 0);
return rtn;
}
/* - Window processing module for POPDOWNMENU window class - */
int PopDownProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
{
switch (msg) {
case CREATE_WINDOW:
return CreateWindowMsg(wnd);
case LEFT_BUTTON:
LeftButtonMsg(wnd, p1, p2);
return FALSE;
case DOUBLE_CLICK:
return TRUE;
case LB_SELECTION:
if (*TextLine(wnd, (int)p1) == LINE)
return TRUE;
wnd->mnu->Selection = (int)p1;
break;
case BUTTON_RELEASED:
if (ButtonReleasedMsg(wnd, p1, p2))
return TRUE;
break;
case BUILD_SELECTIONS:
wnd->mnu = (void *) p1;
wnd->selection = wnd->mnu->Selection;
break;
case PAINT:
if (wnd->mnu == NULL)
return TRUE;
PaintMsg(wnd);
break;
case BORDER:
return BorderMsg(wnd);
case LB_CHOOSE:
LBChooseMsg(wnd, p1);
return TRUE;
case KEYBOARD:
if (KeyboardMsg(wnd, p1, p2))
return TRUE;
break;
case CLOSE_WINDOW:
return CloseWindowMsg(wnd);
default:
break;
}
return BaseWndProc(POPDOWNMENU, wnd, msg, p1, p2);
}
/* --------- compute menu height -------- */
int MenuHeight(struct PopDown *pd)
{
int ht = 0;
while (pd[ht].SelectionTitle != NULL)
ht++;
return ht+2;
}
/* --------- compute menu width -------- */
int MenuWidth(struct PopDown *pd)
{
int wd = 0, i;
int len = 0;
wd = SelectionWidth(pd);
while (pd->SelectionTitle != NULL) {
if (pd->Accelerator) {
for (i = 0; keys[i].keylabel; i++)
if (keys[i].keycode == pd->Accelerator) {
len = max(len, 2+strlen(keys[i].keylabel));
break;
}
}
if (pd->Attrib & CASCADED)
len = max(len, 2);
pd++;
}
return wd+5+len;
}
/* ---- compute the maximum selection width in a menu ---- */
static int SelectionWidth(struct PopDown *pd)
{
int wd = 0;
while (pd->SelectionTitle != NULL) {
int len = strlen(pd->SelectionTitle)-1;
wd = max(wd, len);
pd++;
}
return wd;
}
/* ----- copy a menu command to a display buffer ---- */
int CopyCommand(unsigned char *dest, unsigned char *src,
int skipcolor, int bg)
{
unsigned char *d = dest;
while (*src && *src != '\n') {
if (*src == SHORTCUTCHAR) {
src++;
if (!skipcolor) {
*dest++ = CHANGECOLOR;
*dest++ = cfg.clr[POPDOWNMENU]
[HILITE_COLOR] [BG] | 0x80;
*dest++ = bg | 0x80;
*dest++ = *src++;
*dest++ = RESETCOLOR;
}
}
else
*dest++ = *src++;
}
return (int) (dest - d);
}
[LISTING THREE]
/* ------------- menu.c ------------- */
#include "dflat.h"
static struct PopDown *FindCmd(MBAR *mn, int cmd)
{
MENU *mnu = mn->PullDown;
while (mnu->Title != (void *)-1) {
struct PopDown *pd = mnu->Selections;
while (pd->SelectionTitle != NULL) {
if (pd->ActionId == cmd)
return pd;
pd++;
}
mnu++;
}
return NULL;
}
char *GetCommandText(MBAR *mn, int cmd)
{
struct PopDown *pd = FindCmd(mn, cmd);
if (pd != NULL)
return pd->SelectionTitle;
return NULL;
}
BOOL isCascadedCommand(MBAR *mn, int cmd)
{
struct PopDown *pd = FindCmd(mn, cmd);
if (pd != NULL)
return pd->Attrib & CASCADED;
return FALSE;
}
void ActivateCommand(MBAR *mn, int cmd)
{
struct PopDown *pd = FindCmd(mn, cmd);
if (pd != NULL)
pd->Attrib &= ~INACTIVE;
}
void DeactivateCommand(MBAR *mn, int cmd)
{
struct PopDown *pd = FindCmd(mn, cmd);
if (pd != NULL)
pd->Attrib |= INACTIVE;
}
BOOL isActive(MBAR *mn, int cmd)
{
struct PopDown *pd = FindCmd(mn, cmd);
if (pd != NULL)
return !(pd->Attrib & INACTIVE);
return FALSE;
}
BOOL GetCommandToggle(MBAR *mn, int cmd)
{
struct PopDown *pd = FindCmd(mn, cmd);
if (pd != NULL)
return (pd->Attrib & CHECKED) != 0;
return FALSE;
}
void SetCommandToggle(MBAR *mn, int cmd)
{
struct PopDown *pd = FindCmd(mn, cmd);
if (pd != NULL)
pd->Attrib |= CHECKED;
}
void ClearCommandToggle(MBAR *mn, int cmd)
{
struct PopDown *pd = FindCmd(mn, cmd);
if (pd != NULL)
pd->Attrib &= ~CHECKED;
}
void InvertCommandToggle(MBAR *mn, int cmd)
{
struct PopDown *pd = FindCmd(mn, cmd);
if (pd != NULL)
pd->Attrib ^= CHECKED;
}
[LISTING FOUR]
/* ------------- sysmenu.c ------------ */
#include "dflat.h"
int SystemMenuProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
{
int mx, my;
WINDOW wnd1;
switch (msg) {
case CREATE_WINDOW:
wnd->holdmenu = ActiveMenuBar;
ActiveMenuBar = &SystemMenu;
SystemMenu.PullDown[0].Selection = 0;
break;
case LEFT_BUTTON:
wnd1 = GetParent(wnd);
mx = (int) p1 - GetLeft(wnd1);
my = (int) p2 - GetTop(wnd1);
if (HitControlBox(wnd1, mx, my))
return TRUE;
break;
case LB_CHOOSE:
PostMessage(wnd, CLOSE_WINDOW, 0, 0);
break;
case DOUBLE_CLICK:
if (p2 == GetTop(GetParent(wnd))) {
PostMessage(GetParent(wnd), msg, p1, p2);
SendMessage(wnd, CLOSE_WINDOW, TRUE, 0);
}
return TRUE;
case SHIFT_CHANGED:
return TRUE;
case CLOSE_WINDOW:
ActiveMenuBar = wnd->holdmenu;
break;
default:
break;
}
return DefaultWndProc(wnd, msg, p1, p2);
}
/* ------- Build a system menu -------- */
void BuildSystemMenu(WINDOW wnd)
{
int lf = GetLeft(wnd)+1;
int tp = GetTop(wnd)+1;
int ht = MenuHeight(SystemMenu.PullDown[0].Selections);
int wd = MenuWidth(SystemMenu.PullDown[0].Selections);
WINDOW SystemMenuWnd;
SystemMenu.PullDown[0].Selections[6].Accelerator =
(GetClass(wnd) == APPLICATION) ? ALT_F4 : CTRL_F4;
if (lf+wd > SCREENWIDTH-1)
lf = (SCREENWIDTH-1) - wd;
if (tp+ht > SCREENHEIGHT-2)
tp = (SCREENHEIGHT-2) - ht;
SystemMenuWnd = CreateWindow(POPDOWNMENU, NULL,
lf,tp,ht,wd,NULL,wnd,SystemMenuProc, 0);
#ifdef INCLUDE_RESTORE
if (wnd->condition == ISRESTORED)
DeactivateCommand(&SystemMenu, ID_SYSRESTORE);
else
ActivateCommand(&SystemMenu, ID_SYSRESTORE);
#endif
if (TestAttribute(wnd, MOVEABLE)
#ifdef INCLUDE_MAXIMIZE
&& wnd->condition != ISMAXIMIZED
#endif
)
ActivateCommand(&SystemMenu, ID_SYSMOVE);
else
DeactivateCommand(&SystemMenu, ID_SYSMOVE);
if (wnd->condition != ISRESTORED ||
TestAttribute(wnd, SIZEABLE) == FALSE)
DeactivateCommand(&SystemMenu, ID_SYSSIZE);
else
ActivateCommand(&SystemMenu, ID_SYSSIZE);
#ifdef INCLUDE_MINIMIZE
if (wnd->condition == ISMINIMIZED ||
TestAttribute(wnd, MINMAXBOX) == FALSE)
DeactivateCommand(&SystemMenu, ID_SYSMINIMIZE);
else
ActivateCommand(&SystemMenu, ID_SYSMINIMIZE);
#endif
#ifdef INCLUDE_MAXIMIZE
if (wnd->condition != ISRESTORED ||
TestAttribute(wnd, MINMAXBOX) == FALSE)
DeactivateCommand(&SystemMenu, ID_SYSMAXIMIZE);
else
ActivateCommand(&SystemMenu, ID_SYSMAXIMIZE);
#endif
SendMessage(SystemMenuWnd, BUILD_SELECTIONS,
(PARAM) &SystemMenu.PullDown[0], 0);
SendMessage(SystemMenuWnd, SHOW_WINDOW, 0, 0);
}